package cn.iocoder.yudao.module.vlog.info.dal.mysql;

import cn.iocoder.yudao.framework.business.basic.dao.mapper.CoreMapper;
import cn.iocoder.yudao.framework.business.basic.dao.query.CoreLambdaQueryWrapper;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.api.vlog.info.enums.VLogStatusEnum;
import cn.iocoder.yudao.module.vlog.info.bo.VLogMyActionBO;
import cn.iocoder.yudao.module.vlog.info.dal.dataobject.VLogInfoDO;
import cn.iocoder.yudao.module.vlog.info.vo.AppVLogInfoPageReqVO;
import cn.iocoder.yudao.module.vlog.info.vo.VLogInfoPageReqVO;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import java.math.BigDecimal;
import java.util.List;

/**
 * 视频信息 Mapper
 *
 * @author 山野羡民（1032694760@qq.com）
 */
@Mapper
public interface VLogInfoMapper extends CoreMapper<VLogInfoDO> {

    default PageResult<VLogInfoDO> selectPage(VLogInfoPageReqVO reqVO) {
        return selectPage(reqVO, new CoreLambdaQueryWrapper<VLogInfoDO>()
                .eqIfPresent(VLogInfoDO::getShopId, reqVO.getShopId())
                .eqIfPresent(VLogInfoDO::getCityId, reqVO.getCityId())
                .eqIfPresent(VLogInfoDO::getUserId, reqVO.getUserId())
                .likeIfPresent(VLogInfoDO::getTitle, reqVO.getTitle())
                .eqIfPresent(VLogInfoDO::getPrivacy, reqVO.getPrivacy())
                .eqIfPresent(VLogInfoDO::getStatus, reqVO.getStatus())
                .betweenIfPresent(VLogInfoDO::getCreateTime, reqVO.getCreateTime())
                .orderByDesc(VLogInfoDO::getId));
    }

    default PageResult<VLogInfoDO> selectPage(Long userId, AppVLogInfoPageReqVO reqVO) {
        return selectPage(reqVO, new CoreLambdaQueryWrapper<VLogInfoDO>()
                .eqIfPresent(VLogInfoDO::getShopId, reqVO.getShopId())
                .eqIfPresent(VLogInfoDO::getCityId, reqVO.getCityId())
                .eqIfPresent(VLogInfoDO::getUserId, userId)
                .eqIfPresent(VLogInfoDO::getStatus, reqVO.getStatus())
                .likeIfPresent(VLogInfoDO::getTitle, reqVO.getTitle())
                .betweenIfPresent(VLogInfoDO::getCreateTime, reqVO.getCreateTime())
                .orderByDesc(VLogInfoDO::getId));
    }

    default PageResult<VLogInfoDO> selectEnabledPage(AppVLogInfoPageReqVO reqVO) {
        return selectPage(reqVO, new CoreLambdaQueryWrapper<VLogInfoDO>()
                .eqIfPresent(VLogInfoDO::getShopId, reqVO.getShopId())
                .eqIfPresent(VLogInfoDO::getCityId, reqVO.getCityId())
                .likeIfPresent(VLogInfoDO::getTitle, reqVO.getTitle())
                .eqIfPresent(VLogInfoDO::getPrivacy, false)
                .eqIfPresent(VLogInfoDO::getStatus, VLogStatusEnum.ENABLED.getValue())
                .betweenIfPresent(VLogInfoDO::getCreateTime, reqVO.getCreateTime())
                .orderByDesc(VLogInfoDO::getId));
    }

    @Select("""
            <script>
                    SELECT vi.*
                    FROM vlog_info AS vi
                    WHERE vi.deleted = false AND vi.status = 1 AND vi.privacy = false
                    <if test="cityId != null">
                        AND vi.city_id = #{cityId}
                    </if>
                    ORDER BY RAND()
            </script>
            """)
    Page<VLogInfoDO> selectRandomVLogPage(@Param("page") Page<VLogInfoDO> page, @Param("cityId") Long cityId);

    @Select("""
                    SELECT vi.*,
                           6378.138 * 2 * ASIN(
                                   SQRT(
                                           POW(SIN(('#{latitude}' * PI() / 180 - latitude * PI() / 180) / 2), 2) +
                                           COS('#{latitude}' * PI() / 180) * COS(latitude * PI() / 180) *
                                           POW(SIN(('#{longitude}' * PI() / 180 - longitude * PI() / 180) / 2), 2)
                                   )
                                          ) AS distance
                    FROM vlog_info AS vi
                    WHERE vi.deleted = false AND vi.privacy = false
                    ORDER BY RAND(), distance
            """)
    Page<VLogInfoDO> selectRandomVLogDistancePage(@Param("page") Page<VLogInfoDO> page, @Param("latitude") BigDecimal latitude, @Param("longitude") BigDecimal longitude);

    @Select("""
            SELECT vi.*
            FROM vlog_like AS vl LEFT JOIN vlog_info AS vi ON vi.id = vl.vlog_id
            WHERE vi.deleted = false AND vi.privacy = false AND vl.user_id = #{userId} AND vl.canceled = false
            ORDER BY vl.create_time DESC
            """)
    Page<VLogInfoDO> selectMyLikedVLogPage(@Param("page") Page<VLogInfoDO> page, @Param("userId") Long userId);

    @Select("""
            SELECT vi.*
            FROM vlog_favorite AS vf LEFT JOIN vlog_info AS vi ON vi.id = vf.vlog_id
            WHERE vi.deleted = false AND vi.privacy = false AND vf.user_id = #{userId} AND vf.canceled = false
            ORDER BY vf.create_time DESC
            """)
    Page<VLogInfoDO> selectMyFavoriteVLogPage(@Param("page") Page<VLogInfoDO> page, @Param("userId") Long userId);

    @Select("""
            SELECT vi.*
            FROM member_fans AS vf LEFT JOIN vlog_info AS vi ON vi.user_id = vf.user_id
            WHERE vi.deleted = false AND vi.privacy = false AND vf.fans_user_id = #{userId}
            ORDER BY vf.create_time DESC
            """)
    Page<VLogInfoDO> selectMyFollowVLogPage(@Param("page") Page<VLogInfoDO> page, @Param("userId") Long userId);

    @Select("""
            SELECT vi.*
            FROM member_fans AS vf LEFT JOIN vlog_info AS vi ON vi.user_id = vf.user_id
            WHERE vi.deleted = false AND vi.privacy = false AND vf.fans_user_id = #{userId} AND vf.is_friend = true
            ORDER BY vf.create_time DESC
            """)
    Page<VLogInfoDO> selectMyFriendVLogPage(@Param("page") Page<VLogInfoDO> page, @Param("userId") Long userId);

    @Select("""
            SELECT vi.*
            FROM vlog_comment AS vc LEFT JOIN vlog_info AS vi ON vi.id = vc.vlog_id
            WHERE vi.deleted = false AND vi.privacy = false AND vc.user_id = #{userId}
            ORDER BY vc.create_time DESC
            """)
    Page<VLogInfoDO> selectMyCommentVLogPage(@Param("page") Page<VLogInfoDO> page, @Param("userId") Long userId);

    @Select("""
            SELECT vi.*
            FROM vlog_browse_history AS vb LEFT JOIN vlog_info AS vi ON vi.id = vb.vlog_id
            WHERE vi.deleted = false AND vi.privacy = false AND vb.user_id = #{userId}
            ORDER BY vb.create_time DESC
            """)
    Page<VLogInfoDO> selectMyBrowseHistoryVLogPage(@Param("page") Page<VLogInfoDO> page, @Param("userId") Long userId);

    @Select("""
            <script>
                    SELECT vi.id,
                    IFNULL(vl.id, 0) > 0 AS liked,
                    IFNULL(vf.id, 0) > 0 AS favorite,
                    IFNULL(vc.id, 0) > 0 AS comment,
                    IFNULL(vs.id, 0) > 0 AS follow,
                    IFNULL(vb.id, 0) > 0 AS browse
                    FROM vlog_info vi
                    LEFT JOIN vlog_like vl
                    ON vi.id = vl.vlog_id AND vl.deleted = false AND vl.canceled = false AND vl.user_id = #{userId}
                    LEFT JOIN vlog_favorite vf
                    ON vi.id = vf.vlog_id AND vf.deleted = false AND vf.canceled = false AND vf.user_id = #{userId}
                    LEFT JOIN vlog_comment vc
                    ON vi.id = vc.vlog_id AND vc.deleted = false AND vc.user_id = #{userId}
                    LEFT JOIN member_fans vs
                    ON vi.user_id = vs.user_id AND vs.deleted = false AND vs.fans_user_id = #{userId}
                    LEFT JOIN vlog_browse_history vb
                    ON vi.id = vb.vlog_id AND vb.deleted = false AND vb.user_id = #{userId}
                    <where>
                        <if test="ids != null and ids.size() > 0">
                            vi.id IN
                            <foreach item="item" collection="ids" open="(" separator="," close=")">
                                #{item}
                            </foreach>
                        </if>
                    </where>
                    ORDER BY vi.create_time DESC
            </script>
            """)
    List<VLogMyActionBO> selectMyVLogActions(@Param("userId") Long userId, @Param("ids") List<Long> ids);

    default void updateBrowseCount(Long vlogId) {
        update(null, new LambdaUpdateWrapper<VLogInfoDO>()
                .setSql("browse_count = browse_count + 1")
                .eq(VLogInfoDO::getId, vlogId));
    }

}
